/********************************************************************************
*                                                                               *
* kWookaToolsExecuteProcess.cpp -- some tools execute factory                   *
*                                                                               *
* Copyright (c) Fengren Technology(Guangzhou) Co.LTD. All rights reserved.      *
*                                                                               *
********************************************************************************/


#include "kWookaToolsExecuteProcess.hpp"
#include "wx/wx.h"
#include "wx/process.h"
#include "wx/dir.h"
#include "kWookaProjectInfo.hpp"
#include <wx/txtstrm.h>
#include <wx/wfstream.h>
#include <wx/arrimpl.cpp>
#include "netinfo.h"
#include "kWookaApplicationItemPanel.hpp"
#include "kWooka_perferences_utils.hpp"
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include "kWookaTypedResourceInfo.hpp"


static bool PrepareDatabase(kWookaProcessOutputRender* executor, const wxString& cmd, const wxString& configFile, const wxString& datadir, kWookaProjectInfo* proj, kWookaAppItemInfo* app, wxProcess** procout);
static bool ExecuteCmdline(wxExecuteEnv& env, wxString cmdline, kWookaProcessOutputRender* executor, wxArrayString* outputs);

// RedisExecutorFactory should build the redis execution and make the process ready
wxString kWookaRedisExecutorFactory::BuildCommandLine(kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	return WriteRedisConfig(proj, app);
}



wxProcess* kWookaRedisExecutorFactory::Execute(kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	if (app->GetItemValue(wxT("RedisRemote")) == wxT("remote")) {
		// The mysql database is ready to connect, that will be ok.
		m_isTestOK = true;
		return NULL;
	}

	wxString conf = BuildCommandLine(proj, app);
	if (conf == wxT("ERROR")) {
		// The config file have some error
		return NULL;
	}
	wxExecuteEnv env;
	BuildExecuteEnv(env, proj, app);

	env.cwd = EnsureDirectorString(proj->workspace + wxT("\\") + app->name);

	wxString cmd = app->source + wxT("\\redis-server.exe");
	if (!FileExists(cmd)) {
		cmd = app->source + wxT("\\bin\\redis-server.exe");
		if (!FileExists(cmd)) {
			return false;
		}
	}
	wxString cmdline = cmd + wxT(" \"") + conf + wxT("\"");

	wxProcess* proc = new wxProcess(wxPROCESS_REDIRECT);
	long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
	if (pid == 0) {
		delete proc;
		return NULL;
	}
	proc->SetPid(pid);
	return proc;
}

/*
 * Write the config file and make a test for it. 
 */
bool kWookaRedisExecutorFactory::Prepared(kWookaProcessOutputRender* executor, kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	if (app->GetItemValue(wxT("RedisRemote")) == wxT("remote")) {
		// The mysql database is ready to connect, that will be ok.
		wxExecuteEnv env;
		BuildExecuteEnv(env, proj, app);
		DirectoryExist(env.cwd, true);
		wxString cmd = app->source + wxT("\\redis-cli.exe");
		if (!FileExists(cmd)) {
			cmd = app->source + wxT("\\bin\\redis-cli.exe");
			if (!FileExists(cmd)) {
				if (executor != NULL) {
					executor->SendTextLog(wxT("Could not found the command ") + cmd);
				}
				return false;
			}
		}
		wxString redisServer = app->GetItemValue(wxT("RedisServer"));
		wxString redisPort = app->GetItemValue(wxT("RedisPort"));
		wxString redisDb = app->GetItemValue(wxT("RedisDatabase"));
		wxString redisAuth = app->GetItemValue(wxT("RedisAuthPassword"));
		if (redisDb.IsEmpty()) {
			redisDb = wxT("0");
		}
		wxString cmdline = wxString::Format(wxT("\"%s\" -n %s -h %s -p %s -a %s "), cmd, redisDb, redisServer, redisPort, redisAuth);
		wxArrayString outputs;
		ExecuteCmdline(env, cmdline + wxT(" set __help_test test"), executor, &outputs);
		if (outputs.Count() > 0) {
			for (size_t s = 0; s < outputs.Count(); s++) {
				wxString& line = outputs[s];
				if (wxNOT_FOUND != line.Index(wxT("OK"))) {
					m_isTestOK = true;
				}
			}
		}
		// m_isTestOK = true;
		return m_isTestOK;
	}

	wxString configFile = WriteRedisConfig(proj, app);
	if (configFile == wxT("ERROR")) {
		return false;
	}
	wxExecuteEnv env;
	BuildExecuteEnv(env, proj, app);

	wxString cmd = app->source + wxT("\\redis-server.exe");
	if (!FileExists(cmd)) {
		cmd = app->source + wxT("\\bin\\redis-server.exe");
		if (!FileExists(cmd)) {
			if (executor != NULL) {
				executor->SendTextLog(wxT("Could not found the command ") + cmd);
			}
			return false;
		}
	}
	wxString cmdline = cmd + wxT(" \"") + configFile + wxT("\"");

	wxProcess* proc = new wxProcess(wxPROCESS_REDIRECT);
	long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
	if (pid == 0) {
		delete proc;
		return false;
	}
	proc->SetPid(pid);
	wxInputStream* input = proc->GetInputStream();
	wxInputStream* errinp = proc->GetErrorStream();
	if (input != NULL) {
		wxCSConv gbk(wxT("GBK"));
		wxTextInputStream tins(*input, L" \t", gbk);
		wxTextInputStream terr(*errinp, L" \t", gbk);
		int i = 0;
		do {
			while (input->CanRead()) {
				wxString line = tins.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
			}
			while (errinp->CanRead()) {
				wxString line = terr.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
			}
			wxThread::Sleep(200);
			i++;
		} while (i < 2);
		// delete input;
		bool res = wxProcess::Exists(pid);
		wxProcess::Kill(pid, wxSIGQUIT);
		wxProcess::Kill(pid, wxSIGTERM);
#ifdef WIN32
		if (wxProcess::Exists(pid)) {
			HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
			// try again to kill the process
			if (hProcess != NULL) {
				TerminateProcess(hProcess, 0);
				CloseHandle(hProcess);
			}
		}
#endif
		return res;
	}

	return false;
}



// RedisExecutorFactory should build the redis execution and make the process ready
wxString kWookaNginxExecutorFactory::BuildCommandLine(kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	wxString filename = WriteNginxConfig(proj, app);
	if (filename == wxT("ERROR")) {
		// The config file have some error
		return filename;
	}

	wxString cmd = app->source + wxT("\\nginx.exe");
	if (!FileExists(cmd)) {
		cmd = app->source + wxT("\\sbin\\nginx.exe");
		if (!FileExists(cmd)) {
			return wxT("ERROR");
		}
	}

	DirectoryExist(proj->workspace + wxT("\\nginx\\temp\\"), true);
	DirectoryExist(proj->workspace + wxT("\\nginx\\logs\\"), true);

	return cmd + wxT(" -c") + wxT(" \"") + filename + wxT("\"");;
}

wxProcess* kWookaNginxExecutorFactory::Execute(kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	wxString cmdline = BuildCommandLine(proj, app);
	if (cmdline == wxT("ERROR")) {
		// The config file have some error
		return NULL;
	}
	wxExecuteEnv env;
	BuildExecuteEnv(env, proj, app);

	env.cwd = proj->workspace + wxT("\\nginx");

	wxLogDebug(cmdline);

	wxProcess* proc = new wxProcess(wxPROCESS_REDIRECT);
	long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
	if (pid == 0) {
		delete proc;
		return NULL;
	}
	proc->SetPid(pid);
	return proc;
}

/*
 * Write the config file and make a test for it.
 */
bool kWookaNginxExecutorFactory::Prepared(kWookaProcessOutputRender* executor, kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	wxString configFile = WriteNginxConfig(proj, app);
	if (configFile == wxT("ERROR")) {
		if (executor != NULL) {
			executor->SendTextLog(wxT("The configuration of nginx server is bad."));
		}
		return false;
	}
	wxExecuteEnv env;
	wxGetEnvMap(&env.env);

	BuildExecuteEnv(env, proj, app);

	env.cwd = proj->workspace + wxT("\\nginx");

	wxString cmd = app->source + wxT("\\nginx.exe");
	if (!FileExists(cmd)) {
		cmd = app->source + wxT("\\sbin\\nginx.exe");
		if (!FileExists(cmd)) {
			if (executor != NULL) {
				executor->SendTextLog(wxT("Could not found the command ") + cmd);
			}
			return false;
		}
	}

	DirectoryExist(proj->workspace + wxT("\\nginx\\temp\\"), true);
	DirectoryExist(proj->workspace + wxT("\\nginx\\logs\\"), true);

	wxString cmdline = cmd + wxT(" -t -c") + wxT(" \"") + configFile + wxT("\"");
	
	if (executor != NULL) {
		executor->SendTextLog(wxT("Execute Test command ") + cmdline);
	}

	wxProcess* proc = new wxProcess(wxPROCESS_REDIRECT);
	long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
	if (pid == 0) {
		delete proc;
		return false;
	}
	proc->SetPid(pid);
	wxInputStream* input = proc->GetInputStream();
	wxInputStream* errinp = proc->GetErrorStream();
	bool testResult = false;
	if (input != NULL) {
		wxCSConv gbk(wxT("GBK"));
		wxTextInputStream tins(*input, L" \t", gbk);
		wxTextInputStream terr(*errinp, L" \t", gbk);
		wxArrayString outputs;
		do {
			while (input->CanRead()) {
				wxString line = tins.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
				outputs.Add(line);
			}
			while (errinp->CanRead()) {
				wxString line = terr.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
				outputs.Add(line);
			}
			wxThread::Yield();
		} while (wxProcess::Exists(pid));

		for (size_t i = 0; i < outputs.Count(); i++) {
			wxString line = outputs[i];
			if (line.Index(wxT("is successful")) != wxNOT_FOUND) {
				testResult = true;
				break;
			}
		}
		// delete input;
	}

	return testResult;
}


// RedisExecutorFactory should build the redis execution and make the process ready
wxString kWookaMySQLExecutorFactory::BuildCommandLine(kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	return WriteMySQLConfig(proj, app);
}


wxProcess* kWookaMySQLExecutorFactory::Execute(kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	return this->Execute(NULL, proj, app);
}

wxProcess* kWookaMySQLExecutorFactory::Execute(kWookaProcessOutputRender* render, kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	if (app->GetItemValue(wxT("MySQLRemote")) == wxT("remote")) {
		// The mysql database is ready to connect, that will be ok.
		m_isTestOK = PrepareDatabase(render, wxT(""), wxT(""), wxT(""), proj, app, NULL);
		return NULL;
	}

	wxString conf = BuildCommandLine(proj, app);
	if (conf == wxT("ERROR")) {
		// The config file have some error
		return NULL;
	}
	wxExecuteEnv env;
	BuildExecuteEnv(env, proj, app);

	DirectoryExist(env.cwd, true);
	
	wxString cmd = app->source + wxT("\\bin\\mysqld.exe");
	if (!FileExists(cmd)) {
		cmd = app->source + wxT("\\mysqld.exe");
		if (!FileExists(cmd)) {
			return false;
		}
	}

	wxString datadir = proj->workspace + wxT("\\") + app->name + wxT("\\data");

	if (app->ItemExist(wxT("MySQLDataDir"))) {
		datadir = app->GetItemValue(wxT("MySQLDataDir"));
	}

	DirectoryExist(datadir, true);

	wxString cmdline = cmd + wxT(" --defaults-file=\"") + conf + wxT("\" --console");
	wxProcess* proc = NULL;
	PrepareDatabase(NULL, cmd, conf, datadir, proj, app, &proc);
	if (proc == NULL) {
		proc = new wxProcess(wxPROCESS_REDIRECT);
		long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
		if (pid == 0) {
			delete proc;
			return NULL;
		}
		proc->SetPid(pid);
	}
	return proc;
}


static bool ExecuteCmdline(wxExecuteEnv& env, wxString cmdline, kWookaProcessOutputRender* executor, wxArrayString* outputs) {
	bool result = false;
	wxProcess* proc = new wxProcess(wxPROCESS_REDIRECT);
	long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
	if (pid == 0) {
		delete proc;
		return result;
	}
	proc->SetPid(pid);
	wxInputStream* input = proc->GetInputStream();
	wxInputStream* errinp = proc->GetErrorStream();

	if (input != NULL) {
		wxCSConv gbk(wxT("GBK"));
		wxTextInputStream tins(*input, L" \t", gbk);
		wxTextInputStream terr(*errinp, L" \t", gbk);
		wxThread::Sleep(200);
		do {
			while (input->CanRead()) {
				wxString line = tins.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
				if (outputs != NULL) {
					outputs->Add(line);
				}
				wxLogDebug(line);
				if (!line.IsEmpty()) {
					if (line.Index(wxT("Please use --connect-expired-password option")) != wxNOT_FOUND) {
						result = true;
					}
				}
			}

			while (errinp->CanRead()) {
				wxString line = terr.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
				if (outputs != NULL) {
					outputs->Add(line);
				}
				wxLogDebug(line);
				if (!line.IsEmpty()) {
					if (line.Index(wxT("Please use --connect-expired-password option")) != wxNOT_FOUND) {
						result = true;
					}
				}
			}
			wxThread::Yield();
		} while (wxProcess::Exists(pid));
	}
	return result;
}

/*
 * Write the config file and make a test for it.
 */
bool kWookaMySQLExecutorFactory::Prepared(kWookaProcessOutputRender* executor, kWookaProjectInfo* proj, kWookaAppItemInfo* app) {
	if (app->GetItemValue(wxT("MySQLRemote")) == wxT("remote")) {
		// The mysql database is ready to connect, that will be ok.
		// execute the remote test for this setup
		wxString username = app->GetItemValue(wxT("UserName"));
		wxString passwd = app->GetItemValue(wxT("Password"));
		wxString port = app->GetItemValue(wxT("MySQLPort"));
		wxString dbname = app->GetItemValue(wxT("MySQLDatabase"));
		wxString server = app->GetItemValue(wxT("MySQLServer"));
		wxString testCmd = wxString::Format(wxT("\"%s\\bin\\mysql.exe\" -u%s -p%s --port=%s %s -e \"select 'REMOTESUCCESSFULLY'\""), app->source, username, passwd, port, dbname);
		wxExecuteEnv env;
		wxArrayString outputs;
		bool res = false;
		BuildExecuteEnv(env, proj, app);
		ExecuteCmdline(env, testCmd, executor, &outputs);
		//We will check the results
		for (size_t ss = 0; ss < outputs.Count(); ss++) {
			wxString& line = outputs[ss];
			if (line.Index(wxT("REMOTESUCCESSFULLY")) != wxNOT_FOUND) {
				res = true;
				break;
			}
			else if (line.Index(wxT("'") + dbname + wxT("'")) != wxNOT_FOUND) {
				res = true;
				break;
			}
		}
		return res;
	}
	
	wxString configFile = WriteMySQLConfig(proj, app);
	if (configFile == wxT("ERROR")) {
		return false;
	}
	wxExecuteEnv env;
	BuildExecuteEnv(env, proj, app);

	DirectoryExist(env.cwd, true);
	DirectoryExist(proj->workspace + wxT("\\") + app->name + wxT("\\data"), true);
	DirectoryExist(proj->workspace + wxT("\\") + app->name + wxT("\\temp"), true);

	wxString cmd = app->source + wxT("\\bin\\mysqld.exe");
	if (!FileExists(cmd)) {
		cmd = app->source + wxT("\\mysqld.exe");
		if (!FileExists(cmd)) {
			if (executor != NULL) {
				executor->SendTextLog(wxT("Could not found the command ") + cmd);
			}
			return false;
		}
	}

	wxString cmdline = cmd + wxT(" --defaults-file=\"") + configFile + wxT("\" --validate-config");
	// mysqld --defaults - file = C: / test.ini --validate - config
	wxProcess* proc = new wxProcess(wxPROCESS_REDIRECT);
	long pid = wxExecute(cmdline, wxEXEC_ASYNC, proc, &env);
	if (pid == 0) {
		delete proc;
		return false;
	}
	proc->SetPid(pid);
	wxInputStream* input = proc->GetInputStream();
	wxInputStream* errinp = proc->GetErrorStream();
	bool testResult = false;
	if (input != NULL) {
		wxArrayString  outputs;
		wxCSConv gbk(wxT("GBK"));
		wxTextInputStream tins(*input, L" \t", gbk);
		wxTextInputStream terr(*errinp, L" \t", gbk);
		do {
			while (input->CanRead()) {
				wxString line = tins.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
				outputs.Add(line);
			}
			while (errinp->CanRead()) {
				wxString line = terr.ReadLine();
				if (executor != NULL) {
					executor->SendTextLog(line);
				}
				outputs.Add(line);
			}
			wxThread::Sleep(200);
		} while (wxProcess::Exists(pid));
		// delete input;
		testResult = true;
		for (size_t i = 0; i < outputs.Count(); i++) {
			wxString line = outputs[i];
			if (line.Index(wxT("Aborting")) != wxNOT_FOUND) {
				testResult = false;
				break;
			}
		}
	}
	return testResult;
}

static bool PrepareDatabase(kWookaProcessOutputRender* executor, const wxString& cmd, const wxString& configFile, const wxString& datadir, kWookaProjectInfo* proj, kWookaAppItemInfo* app, wxProcess** procout) {
	wxExecuteEnv env;
	BuildExecuteEnv(env, proj, app);
	wxString rootPassword = app->GetItemValue(wxT("Password"));
	bool remote = app->GetItemValue(wxT("MySQLRemote")) == wxT("remote");
	if (!remote) {
		wxArrayString files;
		wxDir::GetAllFiles(datadir, &files);

		if (files.IsEmpty()) {
			// initialized the data folder
			// find the password in the console
			// "A temporary password is generated for root@localhost"
			wxString initcmdline = cmd + wxT(" --defaults-file=\"") + configFile + wxT("\" -I --console");
			// mysqld --defaults - file = C: / test.ini --validate - config
			wxString passwordFinger = wxT("A temporary password is generated for root@localhost:");

			wxProcess* xproc = new wxProcess(wxPROCESS_REDIRECT);
			long xpid = wxExecute(initcmdline, wxEXEC_ASYNC, xproc, &env);
			if (xpid == 0) {
				delete xproc;
				return false;
			}
			xproc->SetPid(xpid);
			wxInputStream* input2 = xproc->GetInputStream();
			wxInputStream* errinp2 = xproc->GetErrorStream();

			if (input2 != NULL) {
				wxArrayString  outputs;
				wxCSConv gbk(wxT("GBK"));
				wxTextInputStream tins(*input2, L" \t", gbk);
				wxTextInputStream terr(*errinp2, L" \t", gbk);
				do {
					while (input2->CanRead()) {
						wxString line = tins.ReadLine();
						if (executor != NULL) {
							executor->SendTextLog(line);
						}
						outputs.Add(line);
					}
					while (errinp2->CanRead()) {
						wxString line = terr.ReadLine();
						if (executor != NULL) {
							executor->SendTextLog(line);
						}
						outputs.Add(line);
					}
					wxThread::Sleep(200);
				} while (wxProcess::Exists(xpid));
				// delete input;
				for (size_t i = 0; i < outputs.Count(); i++) {
					wxString line = outputs[i];
					if (line.Index(wxT("Aborting")) != wxNOT_FOUND) {
						return false;
						break;
					}
					else if (line.Index(passwordFinger) != wxNOT_FOUND) {
						size_t st = line.Index(passwordFinger);
						rootPassword = line.SubString(st + passwordFinger.Length(), line.Length()).Trim().Trim(false);
					}
				}
			}
		}
		// datadir was initialized successfully.
		// If the mysql initialized successfully, we will do below thing
		// 1. Add a user with the password
		// 2. Call mysql to test and create the database
		if (files.IsEmpty()) {
			wxDir::GetAllFiles(datadir, &files);
		}

		if (files.Count() > 0) { //And we got the root password
			wxString svrcmdline = cmd + wxT(" --defaults-file=\"") + configFile + wxT("\" --console");
			wxProcess* wproc = new wxProcess(wxPROCESS_REDIRECT);
			long wpid = wxExecute(svrcmdline, wxEXEC_ASYNC, wproc, &env);
			if (wpid == 0) {
				delete wproc;
				return false;
			}

			wproc->SetPid(wpid);

			if (procout != NULL) {
				*procout = wproc;
			}

			// So, the server was started,
			// We will 
			// kWookaMySQLServerThread* th = new kWookaMySQLServerThread(executor, wproc);
			// th->Run();

			wxThread::Sleep(1000); // Sleep 1 second to wait the thread

			wxString username = app->GetItemValue(wxT("UserName"));
			wxString passwd = app->GetItemValue(wxT("Password"));
			wxString port = app->GetItemValue(wxT("MySQLPort"));
			wxString dbname = app->GetItemValue(wxT("MySQLDatabase"));
			wxString crtuser = wxString::Format(wxT("DROP USER IF EXISTS '%s'@'%%'; CREATE USER '%s'@'%%' IDENTIFIED BY '%s'; grant all privileges on *.* to '%s'@'%%'; flush privileges;"), username, username, passwd, username);
			wxString rootuser = wxString::Format(wxT("ALTER USER 'root'@'localhost' IDENTIFIED BY '%s'; flush privileges;"), passwd);
			// Now, we will call the method to change the password
			wxString chpwd = wxString::Format(wxT("%s\\bin\\mysql.exe -u root -h localhost --password=\"%s\" --port=%s"), app->source, rootPassword, port);

			// update the user's password
			// if the username is root, we will alter the user's password to new password
			// At the first time, we will change the root's password
			bool cexp = ExecuteCmdline(env, chpwd + wxT(" --connect-expired-password -e \"") + rootuser + wxT("\""), executor, NULL);
			if (cexp) {
				wxLogDebug(wxT("Using --connect-expired-password"));
				chpwd = wxString::Format(wxT("%s\\bin\\mysql.exe -u root -h localhost --connect-expired-password --password=\"%s\" --port=%s"), app->source, rootPassword, port);
				ExecuteCmdline(env, chpwd + wxT(" -e \"") + rootuser + wxT("\""), executor, NULL);
			}
			else {
				wxLogDebug(wxT("Not using --connect-expired-password"));
			}

			rootPassword = passwd;
			if (cexp) {
				chpwd = wxString::Format(wxT("%s\\bin\\mysql.exe -u root -h localhost --password=\"%s\" --port=%s"), app->source, rootPassword, port);
			}
			else {
				chpwd = wxString::Format(wxT("%s\\bin\\mysql.exe -u root -h localhost --password=\"%s\" --port=%s"), app->source, rootPassword, port);
			}

			if (username != wxT("root")) {
				ExecuteCmdline(env, chpwd + wxT(" -e \"") + crtuser + wxT("\""), executor, NULL);
			}
		}

	}
	// if running here, remote or not should all 
	if (true) {
		wxString username = app->GetItemValue(wxT("UserName"));
		wxString passwd = app->GetItemValue(wxT("Password"));
		wxString port = app->GetItemValue(wxT("MySQLPort"));
		wxString dbname = app->GetItemValue(wxT("MySQLDatabase"));
		bool restore = app->GetItemValue(wxT("Restore")) == wxT("restore");
		wxString dumpfile = wxString::Format(wxT("%s\\%s\\dump.sql"), proj->workspace, app->name);
		if (!FileExists(dumpfile)) {
			dumpfile = app->GetItemValue(wxT("RestoreFile"));
		}
		wxString crtdb = wxString::Format(wxT("CREATE DATABASE %s;"), dbname);

		// Now, we will call the method to change the password
		wxString chpwd = wxString::Format(wxT("%s\\bin\\mysql.exe -u%s -h localhost --password=\"%s\" --port=%s"), app->source, username, rootPassword, port);

		// execute the create database cmd
		ExecuteCmdline(env, chpwd + wxT(" -e \"") + crtdb + wxT("\""), executor, NULL);

		if (restore && FileExists(dumpfile, false)) {
			ExecuteCmdline(env, chpwd + wxT(" ") + dbname + wxT("  -e \"\\. ") + dumpfile + wxT("\""), executor, NULL);
		}

		// Ready, now, we will to shutdown this server
		// Wait one second for shutdown
		wxSleep(1);
	}
		// We need to import the basic data
	
	return true;
}

bool kWookaMySQLExecutorFactory::Shutdown(kWookaProcessOutputRender* render, kWookaProjectInfo* proj, kWookaAppItemInfo* app)
{
	if (app->GetItemValue(wxT("MySQLRemote")) != wxT("remote")) {
		wxExecuteEnv env;
		BuildExecuteEnv(env, proj, app);
		wxString cmd = app->source + wxT("\\bin\\mysqld.exe");
		if (!FileExists(cmd)) {
			cmd = app->source + wxT("\\mysqld.exe");
			if (!FileExists(cmd)) {
				if (render != NULL) {
					render->SendTextLog(wxT("Could not found the command ") + cmd);
				}
				return false;
			}
		}
		// The password should update to passwd, so, we will execute the sql by the passwd
		wxString passwd = app->GetItemValue(wxT("Password"));
		wxString port = app->GetItemValue(wxT("MySQLPort"));
		wxString mysqlcmd = wxString::Format(wxT("%s\\bin\\mysql.exe -u root -h localhost --password=\"%s\" --port=%s"), app->source, passwd, port);

		if (app->GetItemValue(wxT("Dump")) == wxT("dump")) {
			wxString dbname = app->GetItemValue(wxT("MySQLDatabase"));
			wxString dumpfile = wxString::Format(wxT("%s\\%s\\dump.sql"), proj->workspace, app->name);
			wxString dumpcmd = wxString::Format(wxT("%s\\bin\\mysqldump.exe -u root -h localhost --password=\"%s\" --port=%s -c -n %s "), app->source, passwd, port, dbname);
			ExecuteCmdline(env, dumpcmd + wxT(" --result-file=\"") + dumpfile + wxT("\""), render, NULL);
		}

		ExecuteCmdline(env, mysqlcmd + wxT(" -e \"shutdown;\""), render, NULL);
		wxSleep(1); //Sleep 1 second after shutdown
		// Clear the data
		if (app->GetItemValue(wxT("ClearDataDir")) == wxT("clear")) {
			wxString datadir = wxString::Format(wxT("%s\\%s\\data"), proj->workspace, app->name);

			if (app->ItemExist(wxT("MySQLDataDir"))) {
				datadir = app->GetItemValue(wxT("MySQLDataDir"));
			}

			// wxDir::Remove(datadir, 1);
			DirectoryRemove(datadir, true);
		}
	}
	else {
		wxString passwd = app->GetItemValue(wxT("Password"));
		wxString svrn = app->GetItemValue(wxT("MySQLServer"));
		wxString username = app->GetItemValue(wxT("UserName"));
		wxString port = app->GetItemValue(wxT("MySQLPort"));
		wxString dbname = app->GetItemValue(wxT("MySQLDatabase"));
		wxExecuteEnv env;
		BuildExecuteEnv(env, proj, app);
		if (app->GetItemValue(wxT("Dump")) == wxT("dump")) {
			wxString dbname = app->GetItemValue(wxT("MySQLDatabase"));
			wxString dumpfile = wxString::Format(wxT("%s\\%s\\dump.sql"), proj->workspace, app->name);
			wxString dumpcmd = wxString::Format(wxT("%s\\bin\\mysqldump.exe -u%s -h localhost --password=\"%s\" --port=%s -c -n %s "), app->source, username, passwd, port, dbname);
			ExecuteCmdline(env, dumpcmd + wxT(" --result-file=\"") + dumpfile + wxT("\""), render, NULL);
		}

		if (app->GetItemValue(wxT("ClearDataDir")) == wxT("clear")) {
			
			wxString cmd = app->source + wxT("\\bin\\mysql.exe");
			if (!FileExists(cmd)) {
				cmd = app->source + wxT("\\mysql.exe");
				if (!FileExists(cmd)) {
					if (render != NULL) {
						render->SendTextLog(wxT("Could not found the command ") + cmd);
					}
					return false;
				}
			}

			wxString cmdline = wxString::Format(wxT("\"%s\" -u%s  -h %s --password=\"%s\" --port=%s -c -n %s "), cmd, username, svrn, passwd, port, dbname);
			wxString dropdb = wxT("DROP DATABASE ") + dbname + wxT(";");
			ExecuteCmdline(env, cmdline + wxT(" -e \"") + dropdb + wxT("\""), render, NULL);
			wxSleep(1);
		}
	}
	return true;
}

kWookaMySQLServerThread::kWookaMySQLServerThread(kWookaProcessOutputRender* executor, wxProcess* proc)
:wxThread() {
	running = false;
	m_render = executor;
	m_proc = proc;
	m_proc->Connect(wxEVT_END_PROCESS, wxProcessEventHandler(kWookaMySQLServerThread::OnProcessEnded), NULL, this);
	m_proc->Detach();
}

void* kWookaMySQLServerThread::Entry() {
	wxInputStream* input = m_proc->GetInputStream();
	wxInputStream* errinp = m_proc->GetErrorStream();
	long pid = m_proc->GetPid();
	running = true;
	kWookaProcessOutputRender* render = m_render;
	if (input != NULL) {
		wxCSConv gbk(wxT("GBK"));
		wxTextInputStream tins(*input, L" \t", gbk);
		wxTextInputStream terr(*errinp, L" \t", gbk);
		do {
			while (running && input->CanRead()) {
				wxString line = tins.ReadLine();
				if (render != NULL) {
					render->SendTextLog(line);
				}
			}
			while (running && errinp->CanRead()) {
				wxString line = terr.ReadLine();
				if (render != NULL) {
					render->SendTextLog(line);
				}
			}

			if (running) {
				wxThread::Yield();
			}
		} while (running);
	}
	return NULL;
}
